package com.pv.bfc.web;

import java.io.IOException;
import java.sql.Blob;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Map;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.Hibernate;
import org.springframework.ui.ModelMap;
import org.springframework.validation.BindException;
import org.springframework.validation.Errors;
import org.springframework.validation.ValidationUtils;
import org.springframework.web.servlet.ModelAndView;
import org.springframework.web.servlet.mvc.AbstractWizardFormController;

import com.pv.bfc.dao.DocumentRepository;
import com.pv.bfc.dao.FolderRepository;
import com.pv.bfc.dao.DocumentRepository.UploadStatus;
import com.pv.bfc.model.Document;
import com.pv.bfc.model.Folder;

@SuppressWarnings("deprecation")
public class DocumentUploadController extends AbstractWizardFormController {

	private FolderRepository folderRepo;
	private DocumentRepository documentRepo;

	private static final Log logger = LogFactory
			.getLog(DocumentUploadController.class);

	/**
	 * Registers the validator and command object.
	 */
	public DocumentUploadController() {
		setCommandClass(DocumentUpload.class);
		setCommandName("upload");
		setPages(new String[] { "selectFolder", "uploadDocument",
				"editDocument" });
	}

	@Override
	protected void postProcessPage(HttpServletRequest request, Object command,
			Errors errors, int page) throws Exception {

		logger.info("IN DocumentUploadController - postProcessPage");

		if (errors.hasErrors()) {
			return;
		}

		DocumentUpload upload = (DocumentUpload) command;

		// When on the second page, we want to write the uploaded file to the
		// web server and store the file size in the upload bean.
		if (page == 1) {
			UploadStatus status = documentRepo.storeDocument(upload);
			if (status.equals(UploadStatus.EXISTS)) {
				errors.rejectValue("document", "error.upload.exists");
			} else if (status.equals(UploadStatus.INVALID)) {
				errors.rejectValue("document", "error.upload.invalid");
			} else if (status.equals(UploadStatus.FAILED)) {
				errors.rejectValue("document", "error.upload.failed");
			}
		}
		logger.info("OUT DocumentUploadController - postProcessPage");
	}

	@Override
	protected void validatePage(Object command, Errors errors, int page) {
		logger.info("IN DocumentUploadController - validatePage");
		DocumentUpload upload = (DocumentUpload) command;
		switch (page) {
		case 0:
			ValidationUtils.rejectIfEmptyOrWhitespace(errors, "folderId",
					"error.upload.required.folder");
			break;
		case 1:
			if (upload.getUpload().getSize() <= 0) {
				errors.rejectValue("document", "error.upload.required.file");
			}
			break;
		}
		logger.info("OUT DocumentUploadController - validatePage");
	}

	@Override
	protected ModelAndView processCancel(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException e)
			throws Exception {
		logger.info("IN DocumentUploadController - processCancel");
		// In case the upload is canceled, we want to remove the file from the
		// server.
		DocumentUpload upload = (DocumentUpload) command;
		documentRepo.deleteDocument(upload.getDocument());
		logger.info("OUT DocumentUploadController - processCancel");
		return new ModelAndView("folders");
	}

	@Override
	protected ModelAndView processFinish(HttpServletRequest request,
			HttpServletResponse response, Object command, BindException e)
			throws Exception {
		logger.info("IN DocumentUploadController - processFinish");

		java.util.Date today = new java.util.Date();
		SimpleDateFormat fmt = new SimpleDateFormat("yyyy-MM-dd");
		String todayStr = fmt.format(today);

		Date dt = java.sql.Date.valueOf(new String(todayStr));

		DocumentUpload upload = (DocumentUpload) command;

		Folder folder = folderRepo.retrieveFolderById(upload.getFolderId());
		folder.addNewDocument(upload.getDocument());

		Document document = (Document) upload.getDocument();

		try {
			Blob blob = Hibernate.createBlob(upload.getUpload()
					.getInputStream());

			document.setContent(blob);
		} catch (IOException exp) {
			exp.printStackTrace();
		}
		document.setFolderId(upload.getFolderId());
		document.setCreatedDate(dt);
		documentRepo.persistDocument(document);

		logger.info("OUT DocumentUploadController - processFinish");

		return new ModelAndView("redirect:folders.htm");
	}

	@SuppressWarnings("unchecked")
	@Override
	protected Map referenceData(HttpServletRequest arg0, int page)
			throws Exception {
		if (page == 0) {
			return new ModelMap(folderRepo.retrieveAllFolders());
		}
		return null;
	}

	public void setFolderRepo(FolderRepository folderRepo) {
		this.folderRepo = folderRepo;
	}

	public void setDocumentRepo(DocumentRepository documentRepo) {
		this.documentRepo = documentRepo;
	}
}
